package com.dimples.dd.admin.config;

import cn.hutool.core.lang.UUID;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import jakarta.servlet.DispatcherType;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import static cn.hutool.http.Method.DELETE;
import static cn.hutool.http.Method.POST;


/**
 * 启用security安全防护
 *
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2024/6/23
 */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class DDAdminMonitorSecurityConfig {

    private final AdminServerProperties adminServer;

    /**
     * 增加 springboot 服务端安全验证 解决客户端注册报401
     * <p>
     * 必须登录才能进入使用
     * <p>
     * protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
     * return http.authorizeHttpRequests((authorizeRequests) -> authorizeRequests.anyRequest().permitAll())
     * .csrf().disable().build();
     * }
     *
     * @param http HttpSecurity
     * @return SecurityFilterChain
     */

    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeHttpRequests((authorizeRequests) -> authorizeRequests //
                .requestMatchers(new AntPathRequestMatcher(this.adminServer.path("/assets/**"))).permitAll()
                .requestMatchers(new AntPathRequestMatcher(this.adminServer.path("/actuator/info"))).permitAll()
                .requestMatchers(new AntPathRequestMatcher(adminServer.path("/actuator/health"))).permitAll()
                .requestMatchers(new AntPathRequestMatcher(this.adminServer.path("/login"))).permitAll()
                .dispatcherTypeMatchers(DispatcherType.ASYNC).permitAll() // https://github.com/spring-projects/spring-security/issues/11027
                .anyRequest().authenticated())
                .formLogin((formLogin) -> formLogin.loginPage(this.adminServer.path("/login"))
                        .successHandler(successHandler))
                .logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout")))
                .httpBasic(Customizer.withDefaults());

        http
                .csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                        .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()).ignoringRequestMatchers(
                                new AntPathRequestMatcher(this.adminServer.path("/instances"), POST.toString()),
        new AntPathRequestMatcher(this.adminServer.path("/instances/*"), DELETE.toString()),
        new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))));

        http.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));

        return http.build();

    }
}
